//  Brett Jones
//  PBR Senior Thesis
//  Copyright Brett Jones October 2007

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Xml;

namespace PBR
{
    /// <summary>
    /// This class holds all of the data pertaining to the painting
    /// </summary>
    public class Painting: IDisposable, IConvertToXml
    {
        //Todo - refactor into GUI
        #region Static Variables
        
        private const float kDiffuseCoef = 1.0f;
        private const float kAmbientCoef = 0.0f;
        private Color kAmbient = Color.FromArgb(255, 255, 255);

        private string kBasePath;
        private string kBlankPath;

        #endregion

        #region Member Variables

        // The collection of all layers
        private List<Layer> mLayers;
        private BitmapUnsafe mBackgroundImage;
        private BitmapUnsafe outputImage;
        private PBRBrush brush;
        private Layer activeLayer;
        private int activeLayerIndex;

        // public variables
        public List<Stroke> StrokeList;
        public KDTreeDLL.KDTree StrokeKDTree;

        public List<Material> MaterialList;
        public Material defaultMaterial;

        private Scene scene;
        
        /// <summary>
        /// Indicates whether the painting should be rendered randomly or from
        /// the stores brush strokes
        /// </summary>
        public bool IsRandom = true;
       
        #endregion


        #region Member Funcitons
        /// <summary>
        /// Default Constructor
        /// </summary>
        public Painting(string basePath, Scene scene)
        {
            //Assign Variables for layers
            kBasePath = basePath;
            kBlankPath = FullPath("blank_512.png");
            this.scene = scene;

            mBackgroundImage = new BitmapUnsafe(kBlankPath, PBR.Properties.Resources.blank_512);

            mLayers = new List<Layer>();

            outputImage = new BitmapUnsafe(kBlankPath, kBlankPath);

            string[] colorPaths = new string[7] {FullPath("brushes/brushC.png"), FullPath("brushes/brushD0.png"),
                    FullPath("brushes/brushD1.png"), FullPath("brushes/brushD2.png"), FullPath("brushes/brushU0.png"),
                    FullPath("brushes/brushU1.png"), FullPath("brushes/brushU2.png")};
            string[] heightPaths = new string[7] {FullPath("brushes/brushHC.png"), FullPath("brushes/brushHD0.png"),
                    FullPath("brushes/brushHD1.png"), FullPath("brushes/brushHD2.png"), FullPath("brushes/brushHU0.png"),
                    FullPath("brushes/brushHU1.png"), FullPath("brushes/brushHU2.png")};

            brush = new PBRBrush(colorPaths, heightPaths);

            mLayers.Add(new Layer(FullPath("white_512.png"), FullPath("white_512.png"), FullPath("white_512.png"),
                    FullPath("white_512.png"), FullPath("white_512.png"), "layer0", scene));
            ActiveLayerIndex = 0;

            defaultMaterial = new Material("Default");
            MaterialList = new List<Material>();
            MaterialList.Add(defaultMaterial);

            // stroke list stuff
            StrokeList = new List<Stroke>();
            StrokeKDTree = new KDTreeDLL.KDTree(2);
        }


        ~Painting()
        {
            foreach (Layer layer in Layers)
            {
                layer.Dispose();
            }
            mBackgroundImage.Dispose();
            outputImage.Dispose();
        }

        public void Dispose()
        {
            foreach (Layer layer in Layers)
            {
                layer.Dispose();
            }
            mBackgroundImage.Dispose();
            outputImage.Dispose();
        }

        public void ConvertToXml(XmlElement root, XmlDocument doc)
        {
            XmlElement painting = doc.CreateElement(XMLSchema.Painting);

            // Add each layer
            foreach (Layer layer in Layers)
            {
                layer.ConvertToXml(painting, doc);
            }

            mBackgroundImage.ConvertToXml(painting, doc);
            outputImage.ConvertToXml(painting, doc);

            brush.ConvertToXml(painting, doc);

            root.AppendChild(painting);
        }

        #endregion


        #region Properties

        public List<Layer> Layers
        {
            get
            {
                return mLayers;
            }
            set
            {
                mLayers = value;
            }
        }

        public BitmapUnsafe BackgroundImage
        {
            get
            {
                return mBackgroundImage;
            }
            set
            {
                mBackgroundImage = value;
            }
        }

        public BitmapUnsafe OutputImage
        {
            get
            {
                return outputImage;
            }
            set
            {
                outputImage = value;
            }
        }

        public PBRBrush Brush
        {
            get
            {
                return brush;
            }
            set
            {
                brush = value;
            }
        }

        public Layer ActiveLayer
        {
            get
            {
                return activeLayer;
            }
            set
            {
                activeLayer = value;
            }
        }

        public int ActiveLayerIndex
        {
            get
            {
                return activeLayerIndex;
            }
            set
            {
                activeLayerIndex = value;
                activeLayer = mLayers[value];
            }

        }

        #endregion

        #region Helper Functions

        private string FullPath(string path)
        {
            return Path.Combine(kBasePath, path);
        }


        #endregion

    }
}
